{% if isFramework("vue") %}
## Testing your Vue Application in NodeJS

We will walk through how you can test AG Grid as part of your Vue application, using default build tools provided when using the [Vue CLI](https://cli.vuejs.org/) utility.

### Waiting for the Grid to be Initialised

Due to the asynchronous nature of AG Grid we cannot simply mount the Grid and assume it'll be ready
for testing in the next step - we need to wait for the Grid to be ready before testing it.

We can do this in one of two ways - wait for the `gridReady` event to be fired, or wait for the Grid API to be set.

The first requires a code change and can be tricky to hook into - the latter is unobtrusive and easier to use.

We can create a utility function that will wait for the Grid API to be set for a set amount of time/attempts:

```js
const ensureGridApiHasBeenSet = vm => new Promise(function (resolve, reject) {
    let timeout = 3000;
    (function waitForGridReady() {
        if (timeout === 0) {
            reject(new Error('Timeout while waiting for AG Grid to initialise'))
        }

        // we need to wait for the gridReady event before we can start interacting with the grid
        // in this case we're looking at the api property in our App component,
        // but it could be anything (ie a boolean flag)
        if (vm.$data.api) {
            // once our condition has been met we can start the tests
            return resolve();
        }

        // not set - wait a bit longer
        timeout =- 10;
        setTimeout(waitForGridReady, 10);
    })();
});
```

We can now use this utility method before each test or in the `beforeEach` to ensure the Grid is fully ready
before continuing with out test:
```js
beforeEach((done) => {
    wrapper = mount(GridExample, {});

    // don't start our tests until the grid is ready
    // it doesn't take long for the grid to initialise, but it is some finite amount of time
    // after the component is ready
    ensureGridApiHasBeenSet(wrapper.vm).then(() => done());
});
```

### Vue Testing Library

An alternative approach would be to use the [Vue Testing Library](https://testing-library.com/docs/vue-testing-library/intro) to test AG Grid. This comes with built in support for handling asynchronous behaviour which you may find easier to work with.

## Testing User Supplied Components

For example, let us suppose a user provides a custom [Editor Component](./cell-editors/) and wants
to test this within the context of the Grid.

```jsx
// Editor Component - Editor.vue
<template>
    <input v-model="value" type="number" style="width: 100%">
</template>

<script>
    export default {
        name: 'Editor',
        data() {
            return {
                value: null
            }
        },
        beforeMount() {
            this.value = this.params.value;
        },
        methods: {
            getValue() {
                return this.value;
            },

            // for testing
            setValue(newValue) {
                this.value = newValue;
            },

            isCancelBeforeStart() {
                return false;
            },

            isCancelAfterEnd() {
                return false;
            }
        }
    }
</script>

<template>
    <ag-grid-vue style="width: 500px; height: 500px;"
                 @grid-ready="onGridReady"
                 :columnDefs="columnDefs"
                 :rowData="rowData">
    </ag-grid-vue>
</template>

<script>
    import {AgGridVue} from "ag-grid-vue3";
    import Editor from './Editor.vue';

    export default {
        name: 'App',
        data() {
            return {
                columnDefs: null,
                rowData: null,
                api: null
            }
        },
        components: {
            AgGridVue,
            Editor
        },
        beforeMount() {
            this.columnDefs = [
                {field: 'make'},
                {
                    field: 'price',
                    editable: true,
                    cellEditor: 'Editor'
                }
            ];

            this.rowData = [
                {make: 'Toyota', price: '35000'},
            ];
        },
        methods: {
            onGridReady(params) {
                this.api = params.api;
            }
        }
    }
</script>
```

We can test the interaction between the Grid and the Editor component via the Grid API:

```js
it('grid renders as expected', () => {
    const cells = wrapper.findAll('.ag-cell-value');
    expect(cells.length).toEqual(2);

    expect(cells.at(0).text()).toEqual('Toyota');
    expect(cells.at(1).text()).toEqual('70000');
});

it('cell should be editable and editor component usable', () => {
    // wait for the api to be set before continuing
    const componentInstance = wrapper.vm;

    const api = componentInstance.$data.api;

    // we use the API to start and stop editing - in a real e2e test we could actually
    // double click on the cell etc
    api.startEditingCell({
        rowIndex: 0,
        colKey: 'price'
    });

    // update the editor input
    const textInput = wrapper.find('input[type="number"]');
    textInput.setValue(100000);

    // stop editing
    api.stopEditing();

    // test the resulting values in the grid (the edited cell value should have changed)
    const cells = wrapper.findAll('.ag-cell-value');
    expect(cells.length).toEqual(2);

    expect(cells.at(0).text()).toEqual('Toyota');
    expect(cells.at(1).text()).toEqual('200000');
});
```

We use the Grid API to initiate and end testing as we're can't readily perform double clicks in a
unit testing environment (but could if doing e2e with something like Protractor for example).

{% /if %}
